/* 
 * File:   Simulation.h
 * Author: cjjonker
 *
 * Created on 20 december 2012, 15:04
 */

#ifndef SIMULATION_H
#define	SIMULATION_H

#include <rfftw.h>             //the numerical simulation FFTW librar
#include <math.h>               //for various math functions
#include "Vector.h"
#include "Dataset.h"
#include "ScalarDataset.h"
#include "VectorDataset.h"
#include "VectorToScalarDataset.h"

class Simulation {

    
    ScalarDataset* data_rho;
    VectorToScalarDataset* data_v;
    VectorToScalarDataset* data_f;
    
    VectorDataset* vdata_v;
    
public:

    
    static const int DIM = 50;				//size of simulation grid

    Simulation();		
    virtual ~Simulation();
    void do_one_simulation_step();
    void init_simulation(size_t n);		
    void insert_force(int X, int Y, double dx, double dy);
    void set_forces();

    void freeze();
    void unfreeze();
    void toggle_frozen();
    bool frozen;               //toggles on/off the animation

    void change_timestep(double change);
    void scale_viscosity(float scale);
    
    ScalarDataset* getRhoDataset() const;
    VectorToScalarDataset* getVDataset() const;
    VectorToScalarDataset* getFDataset() const;
    
    VectorDataset* getVVectorDataset() const;
    
    
    int getDim() const;
    Vector2f getVelocity(int idx) const;
    Vector2f getForce(int idx) const;
    
private:
    void FFT(int direction, void* vx);		
    void solve();
    void diffuse_matter();

    //--- SIMULATION PARAMETERS ------------------------------------------------------------------------

    double dt;				//simulation time step
    float visc;				//fluid viscosity

    fftw_real *vx, *vy;             //(vx,vy)   = velocity field at the current moment
    fftw_real *vx0, *vy0;           //(vx0,vy0) = velocity field at the previous moment
    fftw_real *fx, *fy;	            //(fx,fy)   = user-controlled simulation forces, steered with the mouse
    fftw_real *rho, *rho0;			//smoke density at the current (rho) and previous (rho0) moment
    rfftwnd_plan plan_rc, plan_cr;  //simulation domain discretization
};


inline int Simulation::getDim() const { return Simulation::DIM; }

inline Vector2f Simulation::getVelocity(int idx) const { return Vector2f(vx[idx], vy[idx]); }

inline Vector2f Simulation::getForce(int idx) const { return Vector2f(fx[idx], fy[idx]); }

inline ScalarDataset* Simulation::getRhoDataset() const { return data_rho; } 

inline VectorToScalarDataset* Simulation::getVDataset() const { return data_v; }

inline VectorToScalarDataset* Simulation::getFDataset() const { return data_f; }

inline VectorDataset* Simulation::getVVectorDataset() const { return vdata_v; }

#endif	/* SIMULATION_H */

